package com.wen.util;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

/**
 * @Description:
 * @Author: wenxin
 * @Date: 2022/6/28 11:27
 * @Version: 1.0
 */
public class Scanner extends Thread {
    private String ips;
    private String ports;
    // 日志
    private static Logger logger = Logger.getLogger("Scanner");
    // 使用多线程扫描
    private static ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10,20,1000,
            TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(),
            Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
    private static List<ScanObject> scanObjectList=new ArrayList<>();
    //运行状态
    private static Boolean run=false;

    public Scanner(String ips, String ports) {
        this.ips = ips;
        this.ports = ports;
    }

    /**
     * 开始方法
     * @param ips 输入的待扫描ip列表
     * @param ports 输入的待扫描端口
     */
    public static void start(String ips, String ports) {
        scanObjectList.clear();
        // 解析端口
        String[] portArray = ports.split("-");
        int portStart = Integer.parseInt(portArray[0]);
        int portEnd = Integer.parseInt(portArray[1]);
        logger.info("[-] Ports: " + ports);
        // 解析ip地址，并扫描
        if (ips.indexOf(',') != -1) {
            String[] ipList = ips.split(",");
            logger.info("[-] IP list: " + ipList.toString());
            for (String ip : ipList) {
                scanAllPort(ip,portStart,portEnd);
            }
        }else if (ips.indexOf('/') != -1){
            // TODO 支持ip地址网段的解析
            String[] ipArray = ips.split("/");
            String ipAddress = ipArray[0];
            int mask = Integer.parseInt(ipArray[1]);
            String[] ipSplit = ipAddress.split(".");

        }else {
            scanAllPort(ips,portStart,portEnd);
        }
        // 扫描任务都完成后，程序停止
        try{
            while(true){
                //Map<Integer,List<ScanObject>> s=scanObjectList.stream().collect(Collectors.groupingBy(ScanObject::getState));
                //s.keySet().forEach(x->{
                //    System.out.println(x+":"+s.get(x).size());
                //});
                if(poolExecutor.getActiveCount() == 0){
                    //scanObjectList.forEach(x->{
                    //    System.out.println(x);
                    //});
                    logger.info("[-] Scan job all finish");
                    //System.exit(-1);
                    run=false;
                    break;
                }
                Thread.sleep(1000);
            }
        }catch (Exception ex){
            logger.warning("End with exeception, ex: " + ex.getMessage());
            run=false;
        }
        //System.exit(-1);
    }

    /**
     * 扫描某ip的对应端口
     * @param ip ip地址
     * @param portStart 开始扫描的的端口
     * @param portEnd 停止扫描的端口
     */
    public static void scanAllPort(String ip, int portStart, int portEnd){
        for (int port = portStart; port <= portEnd; port++){
            scan(ip,port);
        }
    }

    /**
     * 对ip:port进行扫描
     * @param ip ip地址
     * @param port 端口
     */
    public static void scan(String ip, int port){
        // 执行扫描任务
        ScanObject obj=new ScanObject(ip,port);
        scanObjectList.add(obj);
        try {
            poolExecutor.execute(new ScanJob(obj,ScanEngine.TCP_FULL_CONNECT_SCAN));
        }catch (Exception ex){
            logger.warning(ex.getMessage());
            obj.setState(-1);
        }
    }

    public List<ScanObject> getScanObjectList() {
        return scanObjectList;
    }
    public void shutdown(){
        poolExecutor.getQueue().clear();
    }
    public void shutdownNow(){
        //poolExecutor.shutdownNow();
        poolExecutor.getQueue().clear();
    }

    public Boolean getRun() {
        return run;
    }


    @Override
    public void run() {
        run=true;
        Scanner.start(ips,ports);
    }
}
